﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ZOIL.DataModel;
using ZOIL.Framework.Presentation;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Threading;
using System.IO;

namespace ZOIL.Library.Components
{
    /// <summary>
    /// Interaction logic for LogoCardView.xaml
    /// </summary>
    [ViewFor(typeof(LogoCard), "default")]
    public partial class LogoCardView : ZComponent
    {
        private static Random _rnd = new Random();

        public static List<LogoCardView> allInstances = new List<LogoCardView>();

        ~LogoCardView()
        {
            allInstances.Remove(this);
        }

        public LogoCardView()
        {
            InitializeComponent();
            allInstances.Add(this);
            Loaded += new RoutedEventHandler(LogoCardView_Loaded);
        }

        void LogoCardView_Loaded(object sender, RoutedEventArgs e)
        {
            img.IsVisibleChanged += new DependencyPropertyChangedEventHandler(img_IsVisibleChanged);
        }

        void img_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue.Equals(true))
            {
                    LogoCardViewModel imgCVM = (LogoCardViewModel)DataContext;
                    if (imgCVM != null)
                        ThreadPool.QueueUserWorkItem(LoadImage, imgCVM.LogoUrl.ToString());
            }
            else
            {
                img.Source = null;
                GC.Collect();
            }
        }

        public void LoadImage(object path)
        {
            //return if null value are file doesn't exists
            Uri uri = new Uri(path.ToString());
            MemoryStream mem = null;
            BitmapDecoder decoder = null;
            //try to load image
            try
            {
                //load into memory
                //synchronze file access -> massive sequential seems to be faster
                byte[] buffer = null;
                Monitor.Enter(CardUtil.FileLoadMonitor);
                try
                {
                    if (File.Exists(uri.LocalPath))
                        buffer = File.ReadAllBytes(uri.LocalPath);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex);
                }
                Monitor.Exit(CardUtil.FileLoadMonitor);

                if (buffer == null)
                    return;

                mem = new MemoryStream(buffer);
                //bitmapdecode
                decoder = BitmapDecoder.Create(uri, BitmapCreateOptions.None, BitmapCacheOption.Default);
                if (decoder != null)
                {
                    BitmapFrame frame = (decoder as BitmapDecoder).Frames.First();
                    //load thumbnail
                    //if (frame.Thumbnail != null)
                    //{
                    //    this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), frame.Thumbnail);
                    //    return;
                    //}
                    //scale down if too big
                    if (frame.Width > CardUtil.MaxCachedImageSize || frame.Height > CardUtil.MaxCachedImageSize)
                    {
                        TransformedBitmap scaledImage = new TransformedBitmap();
                        scaledImage.BeginInit();
                        scaledImage.Source = frame as BitmapSource;

                        // we'll make a reasonable sized thumnbail with a height of 240
                        int pixelH = frame.PixelHeight;
                        int pixelW = frame.PixelWidth;
                        int decodeW;
                        int decodeH;
                        if (frame.PixelWidth > frame.PixelHeight)
                        {
                            decodeW = CardUtil.MaxCachedImageSize;
                            decodeH = (frame.PixelHeight * decodeW) / pixelW;
                        }
                        else
                        {
                            decodeH = CardUtil.MaxCachedImageSize;
                            decodeW = (frame.PixelWidth * decodeH) / pixelH;
                        }
                        double scaleX = decodeW / (double)pixelW;
                        double scaleY = decodeH / (double)pixelH;
                        TransformGroup transformGroup = new TransformGroup();
                        transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
                        scaledImage.Transform = transformGroup;
                        scaledImage.EndInit();
                        // this will disconnect the stream from the image completely ...
                        WriteableBitmap writable = new WriteableBitmap(scaledImage);
                        writable.Freeze();
                        this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), writable);
                    }
                    else
                    {
                        //load full original image
                        this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), frame);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
            finally
            {
                if (mem != null)
                    mem.Close();
            }
        }

        public void SetImage(ImageSource source)
        {
            img.Source = source;
        }

        private void ZComponent_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ((Storyboard)FindResource("MouseDownStoryBoard")).Begin();
        }

        private void ZComponent_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ((Storyboard)FindResource("MouseUpStoryBoard")).Begin();
        }

        private void HandleTabOnButton(object sender, Microsoft.Surface.Presentation.ContactEventArgs e)
        {
            e.Handled = true;
        }
    }
}
